package org.example.init;



import org.example.Interface.ddl.Alter;
import org.example.Interface.ddl.Create;
import org.example.Interface.ddl.Drop;
import org.example.Interface.ddl.Truncate;
import org.example.actuator.ibuilder.AlterBuilder;
import org.example.actuator.ibuilder.CreateBuilder;
import org.example.actuator.ibuilder.DropBuilder;
import org.example.actuator.ibuilder.TruncateBuilder;
import org.example.builder.db2.AlterDb2Builder;
import org.example.builder.db2.CreateDb2Builder;
import org.example.builder.db2.DropDb2Builder;
import org.example.builder.db2.TruncateDb2Builder;
import org.example.builder.mysql.AlterMysqlBuilder;
import org.example.builder.mysql.CreateMysqlBuilder;
import org.example.builder.mysql.DropMysqlBuilder;
import org.example.builder.mysql.TruncateMysqlBuilder;
import org.example.builder.oracle.AlterOracleBuilder;
import org.example.builder.oracle.CreateOracleBuilder;
import org.example.builder.oracle.DropOracleBuilder;
import org.example.builder.oracle.TruncateOracleBuilder;
import org.example.builder.postgresql.AlterPostgresqlBuilder;
import org.example.builder.postgresql.CreatePostgresqlBuilder;
import org.example.builder.postgresql.DropPostgresqlBuilder;
import org.example.builder.postgresql.TruncatePostgresqlBuilder;
import org.example.enums.DbTypeEnum;
import org.example.proxy.ProxyMethod;

import java.lang.reflect.Proxy;
import java.util.*;

public class FactoryBuilder {

    public   static class Builder$Alter {

        public    static  <T> T getBean(Object current){
            try {
                return (T) FactoryBuilder.getBean(current, AlterBuilder.class);
            } catch (Exception e) {
                return null;
            }

        }


    }


    public static class Builder$Create {


        public    static  <T> T getBean(Object current){
            try {
                return (T) FactoryBuilder.getBean(current, CreateBuilder.class);
            } catch (Exception e) {
                return null;
            }


        }


    }


    public  static class Builder$Drop {


        public    static  <T> T getBean(Object current){
            try {
                return (T) FactoryBuilder.getBean(current, DropBuilder.class);
            } catch (Exception e) {
                return null;
            }


        }

    }

    public static class Builder$Truncate {
        public    static  <T> T getBean(Object current){
            try {
                return (T) FactoryBuilder.getBean(current, TruncateBuilder.class);
            } catch (Exception e) {
                return null;
            }


        }

    }

    private   static Object getBean(Object current, Class sign) throws InstantiationException, IllegalAccessException {
        for (Class obj : Context.hashMap.get(current)) {
            if (Arrays.stream(obj.getInterfaces()).anyMatch(v -> v.equals(sign))) {
              return  Proxy.newProxyInstance(           // return obj.newInstance();
                        obj.getClassLoader(),
                        new Class[]{sign(sign)},
                        new ProxyMethod(obj.newInstance())
                );
            }

        }
        return  null;
    }


    public static HashMap<Object, List<Class>> initBuilder() {
        HashMap<Object, List<Class>> hashMap = new LinkedHashMap<>();
        hashMap.put(DbTypeEnum.MYSQL.getDb(), Arrays.asList(
                AlterMysqlBuilder.class, CreateMysqlBuilder.class, DropMysqlBuilder.class, TruncateMysqlBuilder.class
                )
        );
        hashMap.put(DbTypeEnum.DB2.getDb(), Arrays.asList(
                AlterDb2Builder.class, CreateDb2Builder.class, DropDb2Builder.class, TruncateDb2Builder.class
                )
        );
        hashMap.put(DbTypeEnum.ORAClE.getDb(), Arrays.asList(
                AlterOracleBuilder.class, CreateOracleBuilder.class, DropOracleBuilder.class, TruncateOracleBuilder.class
                )
        );
        hashMap.put(DbTypeEnum.POSTGRESQL.getDb(), Arrays.asList(
                AlterPostgresqlBuilder.class, CreatePostgresqlBuilder.class, DropPostgresqlBuilder.class, TruncatePostgresqlBuilder.class
                )
        );
        return hashMap;


    }

    private static Class  sign(Class sign){
        Class[]  list={Alter.class, Create.class, Drop.class, Truncate.class};
        for (Class c:list)
        {
           if (sign.getSimpleName().contains(c.getSimpleName()))
            return  c;
        }
        throw new  RuntimeException();
    }


}
